﻿/*
 * Copyright (c) 2020-2025, Qingdao Digital Intelligent Ship & Ocean Technology Co., Ltd.
 * All rights reserved.
 *
 * This file is part of FastCAE and is distributed under the terms of the
 * BSD 3-Clause License. See the LICENSE file in the project root for details.
 */

#ifndef GEOCOMMANDCOMMON_H_
#define GEOCOMMANDCOMMON_H_

#include <list>
#include <vector>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>

#include <QList>

namespace Geometry
{
    class GeometrySet;
}

namespace OCC
{
    class  FITKOCCComandCommon
    {
    public:
        FITKOCCComandCommon() = default;
        ~FITKOCCComandCommon() = default;

        /**
         * @brief       平铺组合对象。[静态]
         * @param[in]   shape：输入对象[引用]
         * @param[out]  shapes：平铺子对象列表[引用]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-01
         */
        static void FlattenCompShape(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes);

        /**
         * @brief       递归平铺组合对象至非组合对象层级。[静态]
         * @param[in]   shape：组合体或组合对象[引用]
         * @param[out]  shapes：非二维形状列表[引用]
         * @param[out]  shapes2D：二维形状列表[引用]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-01
         */
        static void FlattenCompShape2D(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, QList<TopoDS_Shape> & shapes2D);

        /**
         * @brief       递归平铺组合对象至非组合对象层级。[静态]
         * @param[in]   shape：组合体或组合对象[引用]
         * @param[out]  shapes：非三维形状列表[引用]
         * @param[out]  shapes3D：三维形状列表[引用]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-01
         */
        static void FlattenCompShape3D(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, QList<TopoDS_Shape> & shapes3D);

        /**
         * @brief       递归平铺组合对象至非组合对象层级。[静态]
         * @param[in]   shape：组合体或组合对象[引用]
         * @param[out]  shapes：非二维三维形状列表[引用]
         * @param[out]  shapes2D：二维形状列表[引用]
         * @param[out]  shapes3D：三维形状列表[引用]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-24
         */
        static void FlattenCompShape2D3D(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, 
            QList<TopoDS_Shape> & shapes2D, QList<TopoDS_Shape> & shapes3D);

        /**
         * @brief       递归平铺组合对象至非组合对象层级。[静态]
         * @param[in]   shape：组合体或组合对象[引用]
         * @param[out]  shapes：非独立面、线、点形状列表[引用]
         * @param[out]  shapesBase：独立面、线、点形状列表[引用]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-01
         */
        static void FlattenCompShapeBaseTopo(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, QList<TopoDS_Shape> & shapesBase);

        /**
         * @brief       将给定形状拆分成边并组合成线框。[静态]
         * @param[in]   shape：边、线框或组合体[引用]
         * @param[out]  wires：线框列表[引用]
         * @param[in]   tol：容差[缺省]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-02
         */
        static void MakeWires(const TopoDS_Shape & shape, QList<TopoDS_Wire> & wires, double tol = 1e-6);

        /**
         * @brief       将给定形状拆分成边并组合成线框，根据包围盒尺寸进行分组。[静态]
         * @param[in]   shape：边、线框或组合体[引用]
         * @param[out]  wiresList：线框组列表[引用]
         * @param[in]   tol：容差[缺省]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-03
         */
        static void MakeWires(const TopoDS_Shape & shape, QList<QList<TopoDS_Wire>> & wiresList, double tol = 1e-6);

        /**
         * @brief       将给定形状拆分成边并组合成线框组合对象。[静态]
         * @param[in]   shape：边、线框或组合体[引用]
         * @param[out]  wires：线框组合对象[引用]
         * @param[in]   tol：容差[缺省]
         * @author      ChengHaotian (yeguangbaozi@foxmail.com)
         * @date        2025-09-02
         */
        static void MakeWires(const TopoDS_Shape & shape, TopoDS_Shape & wires, double tol = 1e-6);

        static std::vector<TopoDS_Wire> bulidWire(std::list<TopoDS_Edge>& edgeList);
        static TopoDS_Shape makeFace(std::vector<TopoDS_Wire>& wires);
        static bool isInside(const TopoDS_Wire&, const TopoDS_Wire&);
        static TopoDS_Face validateFace(const TopoDS_Face&);
        static TopoDS_Shape removeSplitter(const TopoDS_Shape& shape);
        static bool isEmpty(const TopoDS_Shape &shape);
        //从inputShape中移除component，返回移除之前的副本
        static TopoDS_Shape removeShape(TopoDS_Shape* inputShape, TopoDS_Shape* component);
        static gp_Ax2 getEdgeAxis(Geometry::GeometrySet* set, int edgeindex);
        static gp_Ax2 getFaceAxis(Geometry::GeometrySet* set, int index);

    private:
        static TopoDS_Shape makeFace(std::list<TopoDS_Wire>&);

    };












    // sort bounding boxes according to diagonal length
    class Wire_Compare : public std::binary_function<const TopoDS_Wire&,
        const TopoDS_Wire&, bool>
    {
    public:
        bool operator() (const TopoDS_Wire& w1, const TopoDS_Wire& w2)
        {
            Bnd_Box box1, box2;
            if (!w1.IsNull())
            {
                BRepBndLib::Add(w1, box1);
                box1.SetGap(0.0);
            }

            if (!w2.IsNull())
            {
                BRepBndLib::Add(w2, box2);
                box2.SetGap(0.0);
            }

            return box1.SquareExtent() < box2.SquareExtent();
        }
    };
}

#endif